package com.yoki.cloud.common.protocol.radius.attribute.parser;

import com.yoki.cloud.common.protocol.radius.attribute.attr.RadiusMsgAttr;
import com.yoki.cloud.common.protocol.radius.attribute.attr.acct.*;
import com.yoki.cloud.common.protocol.radius.attribute.attr.check.*;
import com.yoki.cloud.common.protocol.radius.exception.RadiusException;

/**
 * @author Sky$
 * @Description: TODO
 * @date 2018/1/15$ 16:40$
 */
public class RadiusMsgAttrParser {

    /**
     * 用于将数据包解析成UserPasswordAttr类
     *
     * @param input
     * @param secret
     * @param requestAuthenticator
     * @return
     */
    public static RadiusMsgAttr parsePapPassworld(byte[] input, String secret, byte[] requestAuthenticator) throws RadiusException {
        if (null == input) {
            throw new NullPointerException();
        }
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        if (type != UserPasswordAttr.ATTR_TYPE) {
            throw new IllegalArgumentException("不能将数据转化为此类型的Attribution，Type不一致 !!! " +
                    "当前要求的type为 [" + UserPasswordAttr.ATTR_TYPE + "]，传入的type为 [" + type + "]");
        }
        attr = new UserPasswordAttr(secret, requestAuthenticator);
        attr.parse(input);
        return attr;
    }

    /**
     * 用于将数据包解析成ChapChallengeAttr类
     *
     * @param input
     * @param chapChallengeAttr
     * @return
     */
    public static RadiusMsgAttr parseChapPassworld(byte[] input, ChapChallengeAttr chapChallengeAttr) throws RadiusException {
        if (null == input) {
            throw new NullPointerException();
        }
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        if (type != ChapChallengeAttr.ATTR_TYPE) {
            throw new IllegalArgumentException("不能将数据转化为此类型的Attribution，Type不一致 !!! " +
                    "当前要求的type为 [" + ChapChallengeAttr.ATTR_TYPE + "]，传入的type为 [" + type + "]");
        }
        attr = new ChapPasswordAttr(chapChallengeAttr);
        attr.parse(input);
        return attr;
    }


    /**
     * 用于将数据包解析成RadiusMsgAttr类
     *
     * @param input
     * @return
     */
    public static RadiusMsgAttr parse(byte[] input) throws RadiusException {
        if (null == input) {
            throw new NullPointerException();
        }
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        attr = initAttrByFirst10Type(input);
        if (null == attr) {
            attr = initAttrBy11To20Type(input);
        }
        if (null == attr) {
            attr = initAttrBy21To30Type(input);
        }
        if (null == attr) {
            attr = initAttrBy31To39Type(input);
        }
        if (null == attr) {
            attr = initAttrBy31To39Type(input);
        }
        if (null == attr) {
            attr = initAttrBy40To51Type(input);
        }
        if (null == attr) {
            attr = initAttrBy60To63Type(input);
        }
        if (null != attr) {
            attr.parse(input);
        }
        return attr;
    }

    private static RadiusMsgAttr initAttrByFirst10Type(byte[] input) {
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        switch (type) {
            /** User-Name */
            case UserNameAttr.ATTR_TYPE:
                attr = new UserNameAttr();
                break;
            /** User-Password */
            /*case UserPasswordAttr.ATTR_TYPE:
                attr = new UserPasswordAttr();
                break;*/
            /** CHAP-Password */
            /*case ChapPasswordAttr.ATTR_TYPE:
                attr = new ChapPasswordAttr();
                break;*/
            /** NAS-IP-Address */
            case NasIpAddressAttr.ATTR_TYPE:
                attr = new NasIpAddressAttr();
                break;
            /** NAS-Port */
            case NasPortAttr.ATTR_TYPE:
                attr = new NasPortAttr();
                break;
            /** Service-Type */
            case ServiceTypeAttr.ATTR_TYPE:
                attr = new ServiceTypeAttr();
                break;
            /** Framed-Protocol */
            case FramedProtocolAttr.ATTR_TYPE:
                attr = new FramedProtocolAttr();
                break;
            /** Framed-IP-Address */
            case FramedIpAddressAttr.ATTR_TYPE:
                attr = new FramedIpAddressAttr();
                break;
            /** Framed-IP-Netmask */
            case FramedIpNetmaskAttr.ATTR_TYPE:
                attr = new FramedIpNetmaskAttr();
                break;
            /** Framed-Routing */
            case FramedRoutingAttr.ATTR_TYPE:
                attr = new FramedRoutingAttr();
                break;
            default:
                attr = null;
        }
        return attr;
    }

    private static RadiusMsgAttr initAttrBy11To20Type(byte[] input) {
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        switch (type) {
            /** Filter-Id */
            case FilterIdAttr.ATTR_TYPE:
                attr = new FilterIdAttr();
                break;
            /** Framed-MTU */
            case FramedMTUAttr.ATTR_TYPE:
                attr = new FramedMTUAttr();
                break;
            /** Framed-Compression */
            case FramedCompressionAttr.ATTR_TYPE:
                attr = new FramedCompressionAttr();
                break;
            /** Login-IP-Host */
            case LoginIpHostAttr.ATTR_TYPE:
                attr = new LoginIpHostAttr();
                break;
            /** Login-Service */
            case LoginServiceAttr.ATTR_TYPE:
                attr = new LoginServiceAttr();
                break;
            /** Login-TCP-Port */
            case LoginTcpPortAttr.ATTR_TYPE:
                attr = new LoginTcpPortAttr();
                break;
            /** Reply-Message */
            case ReplyMessageAttr.ATTR_TYPE:
                attr = new ReplyMessageAttr();
                break;
            /** Callback-Number */
            case CallbackNumberAttr.ATTR_TYPE:
                attr = new CallbackNumberAttr();
                break;
            /** Callback-Id */
            case CallbackIdAttr.ATTR_TYPE:
                attr = new CallbackIdAttr();
                break;
            default:
                attr = null;
        }
        return attr;
    }

    private static RadiusMsgAttr initAttrBy21To30Type(byte[] input) {
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        switch (type) {
            /** Framed-Route */
            case FramedRouteAttr.ATTR_TYPE:
                attr = new FramedRouteAttr();
                break;
            /** Framed-IPX-Network */
            case FramedIPXNetworkAttr.ATTR_TYPE:
                attr = new FramedIPXNetworkAttr();
                break;
            /** State */
            case StateAttr.ATTR_TYPE:
                attr = new StateAttr();
                break;
            /** Class */
            case ClassAttr.ATTR_TYPE:
                attr = new ClassAttr();
                break;
            /** Vendor-Specific */
            case VendorSpecificAttr.ATTR_TYPE:
                attr = new VendorSpecificAttr();
                break;
            /** Session-Timeout */
            case SessionTimeoutAttr.ATTR_TYPE:
                attr = new SessionTimeoutAttr();
                break;
            /** Idle-Timeout */
            case IdleTimeoutAttr.ATTR_TYPE:
                attr = new IdleTimeoutAttr();
                break;
            /** Termination-Action */
            case TerminationActionAttr.ATTR_TYPE:
                attr = new TerminationActionAttr();
                break;
            /** Called-Station-Id */
            case CalledStationIdAttr.ATTR_TYPE:
                attr = new CalledStationIdAttr();
                break;
            default:
                attr = null;
        }
        return attr;
    }

    private static RadiusMsgAttr initAttrBy31To39Type(byte[] input) {
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        switch (type) {
            /** Calling-Station-Id */
            case CallingStationIdAttr.ATTR_TYPE:
                attr = new CallingStationIdAttr();
                break;
            /** NAS-Identifier */
            case NasIdentifierAttr.ATTR_TYPE:
                attr = new NasIdentifierAttr();
                break;
            /** Proxy-State */
            case ProxyStateAttr.ATTR_TYPE:
                attr = new ProxyStateAttr();
                break;
            /** Login-LAT-Service */
            case LoginLATServiceAttr.ATTR_TYPE:
                attr = new LoginLATServiceAttr();
                break;
            /** Login-LAT-Node */
            case LoginLATNodeAttr.ATTR_TYPE:
                attr = new LoginLATNodeAttr();
                break;
            /** Login-LAT-Group */
            case LoginLATGroupAttr.ATTR_TYPE:
                attr = new LoginLATGroupAttr();
                break;
            /** Framed-AppleTalk-Link */
            case FramedAppleTalkLinkAttr.ATTR_TYPE:
                attr = new FramedAppleTalkLinkAttr();
                break;
            /** Framed-AppleTalk-Network */
            case FramedAppleTalkNetworkAttr.ATTR_TYPE:
                attr = new FramedAppleTalkNetworkAttr();
                break;
            /** Framed-AppleTalk-Zone */
            case FramedAppleTalkZoneAttr.ATTR_TYPE:
                attr = new FramedAppleTalkZoneAttr();
                break;
            default:
                attr = null;
        }
        return attr;
    }

    private static RadiusMsgAttr initAttrBy40To51Type(byte[] input) {
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        switch (type) {
            /** Acct-Status-Type*/
            case AcctStatusTypeAttr.ATTR_TYPE:
                attr = new AcctStatusTypeAttr();
                break;
            /** Acct-Delay-Time */
            case AcctDelayTimeAttr.ATTR_TYPE:
                attr = new AcctDelayTimeAttr();
                break;
            /** Acct-Input-Octets */
            case AcctInputOctetsAttr.ATTR_TYPE:
                attr = new AcctInputOctetsAttr();
                break;
            /** Acct-Output-Octets */
            case AcctOutputOctetsAttr.ATTR_TYPE:
                attr = new AcctOutputOctetsAttr();
                break;
            /** Acct-Session-Id */
            case AcctSessionIdAttr.ATTR_TYPE:
                attr = new AcctSessionIdAttr();
                break;
            /** Acct-Authentic */
            case AcctAuthenticAttr.ATTR_TYPE:
                attr = new AcctAuthenticAttr();
                break;
            /** Acct-Session-Time */
            case AcctSessionTimeAttr.ATTR_TYPE:
                attr = new AcctSessionTimeAttr();
                break;
            /** Acct-Input-Packets */
            case AcctInputPacketsAttr.ATTR_TYPE:
                attr = new AcctInputPacketsAttr();
                break;
            /** Acct-Output-Packets */
            case AcctOutputPacketsAttr.ATTR_TYPE:
                attr = new AcctOutputPacketsAttr();
                break;
            /** Acct-Terminate-Cause */
            case AcctTerminateCauseAttr.ATTR_TYPE:
                attr = new AcctTerminateCauseAttr();
                break;
            /** Acct-Multi-Session-Id */
            case AcctMultiSessionIdAttr.ATTR_TYPE:
                attr = new AcctMultiSessionIdAttr();
                break;
            /** Acct-Link-Count */
            case AcctLinkCountAttr.ATTR_TYPE:
                attr = new AcctLinkCountAttr();
                break;
            default:
                attr = null;
        }
        return attr;
    }

    private static RadiusMsgAttr initAttrBy60To63Type(byte[] input) {
        RadiusMsgAttr attr = null;
        int type = input[RadiusMsgAttr.INDEX_TYPE];
        switch (type) {
            /** CHAP-Challenge */
            case ChapChallengeAttr.ATTR_TYPE:
                attr = new ChapChallengeAttr();
                break;
            /** NAS-Port-Type */
            case NasPortTypeAttr.ATTR_TYPE:
                attr = new NasPortTypeAttr();
                break;
            /** Port-Limit */
            case PortLimitAttr.ATTR_TYPE:
                attr = new PortLimitAttr();
                break;
            /** Login-LAT-Port */
            case LoginLATPortAttr.ATTR_TYPE:
                attr = new LoginLATPortAttr();
                break;
            default:
                attr = null;
        }
        return attr;
    }


}
